package gui;

import interfaces.TagDataChangedEvent;
import interfaces.TagDataChangedListener;
import interfaces.TagDataGetter;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Date;
import java.util.LinkedList;
import java.util.StringTokenizer;

import javax.swing.*;

import charts.Chart;

import model.Model;

/**
 * @author Manseer Marcel  
 * @author Plavsic Maja
 * @author Pretsch Paul
 */
public class ViewController implements TagDataChangedListener {
	
	private final Model model = new Model();
	private final JTabbedPane tabbedPane = new JTabbedPane();
	private JTextField tagTextField;
	private TimeFramePicker timeFramePicker;
	private Chart piechart; // bar chart used to display data of one or more #-tags
	private Chart barchart; // pie chart used to display data of #- tags of one time space
	private JProgressBar progressBar;
	

	
	/**
	 * Sets up GUI and initiates all objects needed.
	 */
	public void launch() {
		model.addTagDataChangedListener(this);
		JFrame frame = new JFrame("Hashtag Visualizer");
		//Keep running in the background on close
		frame.setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE);
		//call own method on closing window
		frame.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent evt) {
            	quit();
            }
        });		
		
		
		
		//Add components
		Container contentPane = frame.getContentPane();
		contentPane.setLayout(new BorderLayout());
		
		contentPane.add(getNorthPanel(), BorderLayout.NORTH);
		//contentPane.add(getCenterPanel(), BorderLayout.CENTER);
		contentPane.add(getCenterTabbedPane(), BorderLayout.CENTER);
		contentPane.add(getSouthPanel(), BorderLayout.SOUTH);
		
		//Prepare and make visible
		//frame.setLocation(400, 200);
		frame.setSize(500, 400);
		frame.pack();		
		progressBar.setVisible(false);
		frame.setVisible(true);
	}
	
	/**
	 * Closes all open connections and cancels queries
	 * in preparation for shutdown.
	 */
	public void quit() {
		model.cancelAllQueries();
		System.exit(0);
	}
	
	//******* PRIVATE
	
	//*** PANELS
	
	/**
	 * Returns the JPanel that will be displayed north of the main window.
	 */
	private JPanel getNorthPanel() {
		//hashtag text field
		JPanel textPanel = new JPanel();
		textPanel.setBorder(BorderFactory.createTitledBorder("#hashtags"));
		tagTextField = new JTextField(27);
		tagTextField.addActionListener(textFieldEditedListener);
		tagTextField.setHorizontalAlignment(JTextField.RIGHT);
		textPanel.add(tagTextField);
		
		//Time frame picker
		timeFramePicker = new TimeFramePicker();
		timeFramePicker.last24hButton.addActionListener(textFieldEditedListener);
		timeFramePicker.last3daysButton.addActionListener(textFieldEditedListener);
		timeFramePicker.lastWeekButton.addActionListener(textFieldEditedListener);
		
		//Abort button
		JButton abortButton = new JButton("Abort");
		abortButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				model.cancelAllQueries();
			}
		});
		
		//Final panel
		JPanel northPanel = new JPanel();
		northPanel.setLayout(new FlowLayout());
		
		northPanel.add(timeFramePicker);
		northPanel.add(textPanel);
		northPanel.add(abortButton);
		
		return northPanel;
	}
	
	/**
	 * Returns the JPanel that will be displayed in the center of the main window.
	 * (Should return a chart of any type, depending on the data to be visualized)
	 */
	/*private JPanel getCenterPanel() {
		chart = new charts.BarChart();
		//chart = new charts.PieChart();
		chart.prepareDataSet(new Date(), "please enter Tags");
		return chart;
	}*/
	
	/**
	 * Return the JTabbedPane which includes the bar chart and the pie chart.
	 * @return tabbedPane
	 */
	private JTabbedPane getCenterTabbedPane() {
		tabbedPane.addTab("Bar Chart", getBarChartPanel());
		tabbedPane.addTab("Pie Chart", getPieChartPanel());
		return tabbedPane;
	}
	
	
	/**
	 * Returns a JFreeChart, to show data in a bar chart
	 * @return barchart
	 */
	private JPanel getBarChartPanel() {
		barchart = new charts.BarChart();
		barchart.prepareDataSet(new Date(), "please enter Tags");
		return barchart;
	}
	
	
	/**
	 * Returns a JFreeChart, to show data in a pie chart
	 * @return piechart
	 */
	private JPanel getPieChartPanel() {
		piechart = new charts.PieChart();
		piechart.prepareDataSet(new Date(), "please enter Tags");
		return piechart;
	}
	

	/**
	 * Returns the JPanel that will be displayed south of the main window.
	 */

	private JPanel getSouthPanel() {
		JPanel panel = new JPanel();
		panel.setLayout(new FlowLayout());
		
		progressBar = new JProgressBar();
		progressBar.setIndeterminate(true); //fetching tweet count is always indeterminate
		panel.add(progressBar);
		
		return panel;
	}
	
	//*** ASSISTING METHODS	
	
	/**
	 * Extracts the hashtags contained in a string. Every word starting
	 * with '#' is considered to be a tag.
	 */
	private String[] extractTagsFromString(String text) {
		if (text == null) return new String[0];
		java.util.List<String> list = new LinkedList<String>();
		
		StringTokenizer parser = new StringTokenizer(text, " ,", false);
		while (parser.hasMoreTokens()) {
			String token = parser.nextToken();
			if ((token.length() > 1) && (token.startsWith("#"))) { 
				list.add(token); 
			}
		}
			
		return list.toArray(new String[list.size()]);
	}
	
	//*** LISTENERS
	
	private ActionListener textFieldEditedListener = new ActionListener() {

		@Override
		public void actionPerformed(ActionEvent e) {
			String[] tags = extractTagsFromString(tagTextField.getText());
			
			model.cancelAllQueries(); //cancel all previous queries
			piechart.prepareDataSet(timeFramePicker.getSelectedDaySince(), tags);
			barchart.prepareDataSet(timeFramePicker.getSelectedDaySince(), tags);
			System.out.println(String.format("VC: Requesting tag count for \"%s\" since %s", tagTextField.getText(), timeFramePicker.getSelectedDaySince()));
			
			model.requestTweetCountForTagSince(timeFramePicker.getSelectedDaySince(), tags);
		}
	};

	@Override
	public void handleTagDataChanged(TagDataChangedEvent e) {
		TagDataGetter source = e.getSource();
		
		System.out.println(String.format("VC: Received request update for tag: %s on day: %s (- %d + %d)", source.getTag(), source.getDate(), e.getOldCount(), source.getCount()));
		
		piechart.setTagData(source, e.getOldCount());
		barchart.setTagData(source, e.getOldCount());

		if (source.getFinished()) {
			progressBar.setVisible(false);
		} else {
			progressBar.setVisible(true);
		}
	}
}
